from wheels.pi.coro._TaskProcessor import TaskProcessor as _TaskProcessor
from wheels.pi.coro._TaskScheduler import TaskScheduler as _TaskScheduler
from wheels.pi.coro._AIOScheduler import AIOScheduler as _AIOScheduler



class Kernel(object):

    def __init__(self):
        self._task_processor = _TaskProcessor(self)
        self._task_scheduler = _TaskScheduler(self._task_processor)
        self._aio_scheduler = _AIOScheduler(self._task_scheduler)
        self._init_tid = self._create_task(_init(self), -1)
        self._schedule_task(self._init_tid)
        self._halt = False


    def exec_task(self, coro):
        tid = self._create_task(coro, self._init_tid)
        self._schedule_task(tid)


    def main(self):
        self._task_scheduler.run()


    def _create_task(self, coro, parent_tid):
        return self._task_scheduler.create_task(coro, parent_tid)


    def _schedule_task(self, tid, val=None, err=None):
        self._task_scheduler.schedule_task(tid, val, err)


    def _terminate_task(self, tid, status=None, killed=False):
        self._task_scheduler.terminate_task(tid, status, killed)


    def _system_call(self, call, tid):
        call.exec_(self, tid)


    def _sys_tid(self, tid):
        self._task_scheduler.task_tid(tid)


    def _sys_cmd(self, tid):
        self._task_scheduler.task_cmd(tid)


    def _sys_pid(self, tid):
        self._task_scheduler.task_pid(tid)


    def _sys_kill(self, tid, target_tid):
        self._task_scheduler.task_kill(tid, target_tid)


    def _sys_fork(self, tid, coro):
        self._task_scheduler.task_fork(tid, coro)


    def _sys_wait(self, tid, target_tid):
        self._task_scheduler.task_wait(tid, target_tid)


    def _sys_exit(self, tid, status):
        self._task_scheduler.task_exit(tid, status)


    def _sys_halt(self, tid):
        self._halt = True


    def _sys_accept(self, tid, handle):
        self._aio_scheduler.schedule_accept(tid, handle)


    def _sys_connect(self, tid, handle, remote_address):
        self._aio_scheduler.schedule_connect(tid, handle, remote_address)


    def _sys_recv(self, tid, handle, cnt):
        self._aio_scheduler.schedule_recv(tid, handle, cnt)


    def _sys_send(self, tid, handle, buf):
        self._aio_scheduler.schedule_send(tid, handle, buf)



def _aio(kernel):
    while True:
        kernel._aio_scheduler.run()
        yield



def _init(kernel):
    aio_tid = yield Fork(_aio(kernel))
    while not kernel._halt:
        yield
    yield Kill(aio_tid)



from wheels.pi.coro import Fork
